package Underworld_Survival;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.io.File;
import java.nio.file.Paths;

import static Underworld_Survival.Game.stage;
import static Underworld_Survival.Game.stageOfMerchantAppears;

public class GameDataSaveManager {
    private static final String SAVE_FILE = "saves/Software_Copyright.sav";

    // 保存游戏（入口方法）
    public static void saveGame(Player player) throws IOException {
        File saveFile = new File(SAVE_FILE);
        // 确保目录存在
        File parentDir = saveFile.getParentFile();
        if (!parentDir.exists()) {
            boolean success = parentDir.mkdirs(); // 创建多级目录
            if (!success) {
                System.err.println("无法创建存档目录: " + parentDir.getAbsolutePath());
                return;
            }
        }
        GameSaveData data = convertToSaveData(player);
        writeToFile(data,saveFile);
    }

    // 转换为存档数据
    private static GameSaveData convertToSaveData(Player player) {
        GameSaveData data = new GameSaveData();

        //游戏进度
        data.currentStage=stage;
        data.stageOfMerchantAppears=stageOfMerchantAppears[0];

        //移除player所有正在生效的效果（武器，防具，鞋子，buff,增益等，因为这些会在重新获得时再次触发）
        player.getEffectManager().purgeAllEffects(player);
        //！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！
        //需要注意：只能在退出游戏的时候才能保存游戏数据，游戏进行中保存数据会修改player的属性数值
        //player.getEffectManager().purgeAllEffects(player)这个的使用同时会改变游戏中也仅是传进来的player的数据

        // 基础属性
        data.pName=player.getName();
        data.pCurrentHP=player.getCurrentHP();
        data.pBaseMaxHP=player.getBaseMaxHP();
        data.pBonusMaxHP=player.getBonusMaxHP();
        data.pTotalMaxHP=player.getTotalMaxHP();
        data.pCurrentAgi=player.getCurrentAgi();
        data.pBaseMaxAgi=player.getBaseMaxAgi();
        data.pBonusMaxAgi=player.getBonusMaxAgi();
        data.pTotalMaxAgi=player.getTotalMaxAgi();
        data.pBaseStr=player.getBaseStr();
        data.pBonusStr=player.getBonusStr();
        data.pTotalStr=player.getTotalStr();
        data.pBaseDef=player.getBaseDef();
        data.pBonusDef=player.getBonusDef();
        data.pTotalDef=player.getTotalDef();
        data.pBaseEP=player.getBaseEP();
        data.pBonusEP=player.getBonusEP();
        data.pTotalEP=player.getTotalEP();
        data.pBaseCritRate=player.getBaseCritRate();
        data.pBonusCritRate=player.getBonusCritRate();
        data.pTotalCritRate=player.getTotalCritRate();
        data.pBaseCritMultiplier=player.getBaseCritMultiplier();
        data.pBonusCritMultiplier=player.getBonusCritMultiplier();
        data.pTotalCritMultiplier=player.getTotalCritMultiplier();

        //效果管理器的数据储存
        //data.effectManagerData=player.getEffectManager().toArchive();

        // 装备槽位
        data.pWeaponSlot=null;
        data.pArmorSlot=null;
        data.pShoeSlot=null;
        if(player.getWeaponSlot().hasWeapon()){
            data.pWeaponSlot=player.getWeaponSlot();
        }
        if(player.getArmorSlot().hasArmor()){
            data.pArmorSlot=player.getArmorSlot();
        }
        if(player.getShoeSlot().hasShoe()){
            data.pShoeSlot=player.getShoeSlot();
        }

        // Buff状态
        player.getBuff().forEach(buff ->
                data.pActiveBuffs.add(new GameSaveData.BuffData(
                        buff.getBuffId(),
                        buff.getRemainingDuration()
                )));

        // 背包物品
        player.bag.getConsolidatedBag().forEach((itemId, count) -> {
                data.inventory.put(itemId, count);
        });
        data.pGold=player.bag.getGold();
        data.pDiamond=player.bag.getDiamond();

        // 已学习技能
        player.ability.getActiveSkill().forEach(skill ->
                data.learnedSkills.add(skill.getSkillId()));

        return data;
    }

    // 加载游戏（入口方法）
    public static Player loadGame() throws IOException, ClassNotFoundException {
        GameSaveData data = readFromFile();
        return rebuildPlayer(data);
    }

    // 重建玩家对象
    private static Player rebuildPlayer(GameSaveData data) {
        Player player = new Player();

        //重建游戏进度
        stage=data.currentStage;
        stageOfMerchantAppears[0]=data.stageOfMerchantAppears;

        // 恢复基础属性
        player.setName(data.pName);
        player.setCurrentHP(data.pCurrentHP);
        player.setBaseMaxHP(data.pBaseMaxHP);
        player.setBonusMaxHP(data.pBonusMaxHP);
        player.setTotalMaxHP(data.pTotalMaxHP);
        player.setCurrentAgi(data.pCurrentAgi);
        player.setBaseMaxAgi(data.pBaseMaxAgi);
        player.setBonusMaxAgi(data.pBonusMaxAgi);
        player.setTotalMaxAgi(data.pTotalMaxAgi);
        player.setBaseStr(data.pBaseStr);
        player.setBonusStr(data.pBonusStr);
        player.setTotalStr(data.pTotalStr);
        player.setBaseDef(data.pBaseDef);
        player.setBonusDef(data.pBonusDef);
        player.setTotalDef(data.pTotalDef);
        player.setBaseEP(data.pBaseEP);
        player.setBonusEP(data.pBonusEP);
        player.setTotalEP(data.pTotalEP);
        player.setBaseCritRate(data.pBaseCritRate);
        player.setBonusCritRate(data.pBonusCritRate);
        player.setTotalCritRate(data.pTotalCritRate);
        player.setBaseCritMultiplier(data.pBaseCritMultiplier);
        player.setBonusCritMultiplier(data.pBonusCritMultiplier);
        player.setTotalCritMultiplier(data.pTotalCritMultiplier);

        //重置player效果管理器
        //player.getEffectManager().loadFromArchive(data.effectManagerData);

        // 重建装备槽
        if (data.pWeaponSlot != null) {
            player.equipWithEquipment((Equipment) GameRegistry.createItem(data.pWeaponSlot.getEquippedItemId()));
        }
        if (data.pArmorSlot != null) {
            player.equipWithEquipment((Equipment) GameRegistry.createItem(data.pArmorSlot.getEquippedItemId()));
        }
        if (data.pShoeSlot != null) {
            player.equipWithEquipment((Equipment) GameRegistry.createItem(data.pShoeSlot.getEquippedItemId()));
        }

        // 重建Buff
        data.pActiveBuffs.forEach(buffData -> {
            Buff buff = GameRegistry.createBuff(buffData.buffId);
            buff.setRemainingDuration(buffData.remainingTurns);
            player.addBuff(buff);
        });

        // 重建背包
        data.inventory.forEach((id, count) -> {
            // 优先尝试作为装备加载
            Item item = GameRegistry.createItem(id);
            player.obtainItem(item);
        });

        player.bag.setGold(data.pGold);
        player.bag.setDiamond(data.pDiamond);

        // 重建技能
        data.learnedSkills.forEach(skillId ->
                player.learnSkill(GameRegistry.createSkill(skillId)));
        return player;
    }

    // 文件读写方法
    private static void writeToFile(GameSaveData data,File saveFile) throws IOException {
        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(saveFile))) {
            oos.writeObject(data);
        }
    }

    private static GameSaveData readFromFile() throws IOException, ClassNotFoundException {
        File saveFile = new File(SAVE_FILE);
        // 确保目录存在
        File parentDir = saveFile.getParentFile();
        if (!parentDir.exists()) {
            boolean success = parentDir.mkdirs(); // 创建多级目录
            if (!success) {
                System.err.println("无法创建存档目录: " + parentDir.getAbsolutePath());
                throw new IllegalStateException("无法创建！1！！");
            }
        }
        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(saveFile))) {
            return (GameSaveData) ois.readObject();
        }
    }
}